package cn.wgx.commons.handler;


import cn.wgx.commons.exception.cn.CGNoPermissionException;
import cn.wgx.commons.exception.cn.TooFastRequestException;
import cn.wgx.commons.security.shiro.exception.SessionKickException;
import cn.wgx.commons.storage.fastdfs.exception.FdfsException;
import cn.wgx.commons.util.StringUtils;
import cn.wgx.modules.base.web.BaseController;
import com.alibaba.fastjson.JSONException;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.naming.NoPermissionException;
import java.lang.reflect.UndeclaredThrowableException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 *  全局exception拦截
 */
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler extends BaseController {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @ExceptionHandler(value = Exception.class)
    private Map<String,Object> exceptionHandler(Exception e){
        Map<String,Object> map = getInitMap();
        if(e instanceof NoPermissionException || e instanceof UndeclaredThrowableException){
            returnErrorMap("无权访问此接口.", map);
        }else if(e instanceof DataAccessException){
            returnErrorMap("数据错误或数据超出长度限制.", map);
        }else if(e instanceof SQLException){
            returnErrorMap("数据库错误.", map);
        }else if(e instanceof SessionKickException){
            returnErrorMap("此账户已在他处登录.", map);
        }else if(e instanceof UnknownAccountException){
            returnErrorMap("资源服务器连接错误.", map);
        }else if(e instanceof UnauthenticatedException){
            returnErrorMap("请登陆后再进行操作.", 401,  map);
        }else if(e instanceof FdfsException){
            returnErrorMap("资源服务器连接错误.", map);
        }else if(e instanceof JSONException){
            returnErrorMap("JSON解析错误. ", map);
        }else if(e instanceof HttpMessageNotReadableException){
            returnErrorMap("请求体参数错误. json解析失败.", map);
        }else if(e instanceof MethodArgumentTypeMismatchException){
            returnErrorMap( "参数类型错误. ", map);
        }else if(e instanceof ServletRequestBindingException){
            returnErrorMap("缺少参数:  " + e.getMessage(), map);
        }else if(e instanceof ShiroException){
            returnErrorMap("权限问题.", map);
        }else if(e instanceof HttpMediaTypeNotAcceptableException){
            returnErrorMap("404.", map);
        }else if(e instanceof CGNoPermissionException){
            returnErrorMap(((CGNoPermissionException) e).getErrorMsg(), map);
        }else if(e instanceof TooFastRequestException){
            returnErrorMap(((TooFastRequestException) e).getMsg(), map);
        }else if(e instanceof NullPointerException){
            returnErrorMap("空空", map);
        }else if(e instanceof RuntimeException){
            returnErrorMap( "系统错误或参数有误,请调整后再试", map);
            logger.error("RuntimeException : -> {}", StringUtils.join(e.getStackTrace()));

        }else{
            returnErrorMap( "系统内部问题,请稍后再试.", map);
            logger.error("other error: -> {}", StringUtils.join(e.getStackTrace()));
        }
        if(logger.isDebugEnabled()){
            e.printStackTrace();
            map.put("debug", e.getMessage());
            //map.put("debug2", StringUtils.join(e.getStackTrace()));
            logger.debug(e.getMessage());
        }
        return map;
    }


    @ExceptionHandler(value = DuplicateKeyException.class)
    private Map<String,Object> duplicateExceptionHandler(DuplicateKeyException e){
        String errMsg = e.getMessage();
        if(errMsg.contains("username")){
            return returnErrorMap("用户名已被占用.");
        }else{
            return returnErrorMap("duplicate error.");
        }
    }
}
